package server2;

import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.mina.core.session.IoSession;

import protocol.ProtoHead;
import util.DataTypeTranslater;

/**
 * 瀛樻斁缃戠粶閫氫俊姣忎竴涓姹傜殑瀵硅薄锛堝皢鏀惧叆闃熷垪锛�
 * 
 * @author Feng
 */
public class NetworkPacket {
	// 淇℃伅涓殑int鎵�鍗犵殑瀛楄妭鏁�
	public static final int HEAD_INT_SIZE = 4;
	// 淇℃伅涓殑floats鎵�鍗犵殑瀛楄妭鏁�
	public static final int HEAD_FLOAT_SIZE = 4;

	public IoSession ioSession;
	public byte[] arrayBytes;

	public NetworkPacket(IoSession ioSession, byte[] arrayBytes) {
		this.ioSession = ioSession;
		this.arrayBytes = arrayBytes;
	}

	/**
	 * 鑾峰彇璇锋眰鐨勯暱搴�
	 * 
	 * @return int
	 * @author Feng
	 */
	public int getMessageLength() {
		// return arrayBytes.length;
		return getMessageLength(arrayBytes);
	}

	public static int getMessageLength(byte[] array) {
		return array.length;
		// return DataTypeTranslater.bytesToInt(array, getSizeStartIndex());
	}

	/**
	 * 鑾峰彇璇锋眰绫诲瀷
	 * 
	 * @return ProtoHead.ENetworkMessage
	 * @author Feng
	 */
	public ProtoHead.ENetworkMessage getMessageType() {
		return getMessageType(arrayBytes);
	}

	public static ProtoHead.ENetworkMessage getMessageType(byte[] array) {
		return ProtoHead.ENetworkMessage.valueOf(util.DataTypeTranslater.bytesToInt(array, HEAD_INT_SIZE));
	}

	/**
	 * 鑾峰彇MessageId
	 * 
	 * @return byte[]
	 * @author Feng
	 */
	public byte[] getMessageID() {
		return getMessageID(arrayBytes);
	}

	public static byte[] getMessageID(byte[] array) {
		int offset = getMessageIdStartIndex();
		byte[] messageIdBytes = new byte[HEAD_FLOAT_SIZE];
		for (int i = 0; i < messageIdBytes.length; i++)
			messageIdBytes[i] = array[offset + i];

		return messageIdBytes;
	}

	/**
	 * 鑾峰彇娑堟伅鐨勫璞yte鏁扮粍
	 * 
	 * @return byte[]
	 * @author Feng
	 */
	public byte[] getMessageObjectBytes() {
		return getMessageObjectBytes(arrayBytes);
	}

	public static byte[] getMessageObjectBytes(byte[] array) {
		// System.out.println(getMessageLength(array) -
		// getMessageObjectStartIndex());
		byte[] response = new byte[getMessageLength(array) - getMessageObjectStartIndex()];
		for (int i = 0; i < response.length; i++)
			response[i] = array[getMessageObjectStartIndex() + i];

		return response;
	}

	/**
	 * 鎵撳寘鎴愬彲浠ュ彂閫佺殑byte[]
	 * 
	 * @param messageType
	 * @param packetBytes
	 * @return byte[]
	 * @throws IOException
	 * @author Feng
	 */
	public static byte[] packMessage(int messageType, byte[] packetBytes) throws IOException {
		return packMessage(messageType, ServerModel.createMessageId(), packetBytes);
	}

	public static byte[] packMessage(int messageType, byte[] messageIdBytes, byte[] packetBytes) throws IOException {
		int size = getMessageObjectStartIndex() + packetBytes.length;
		byte[] messageBytes = new byte[size];

		// 1.娣诲姞size
		byte[] sizeBytes = DataTypeTranslater.intToByte(size);
		for (int i = 0; i < sizeBytes.length; i++)
			messageBytes[i] = sizeBytes[i];

		// 2.鍔犲叆绫诲瀷
		byte[] typeBytes = DataTypeTranslater.intToByte(messageType);
		for (int i = 0; i < typeBytes.length; i++)
			messageBytes[getTypeStartIndex() + i] = typeBytes[i];

		// 3.娣诲姞MessageId
		for (int i = 0; i < messageIdBytes.length; i++)
			messageBytes[getMessageIdStartIndex() + i] = messageIdBytes[i];

		// 4.鍔犲叆鏁版嵁鍖�
		for (int i = 0; i < packetBytes.length; i++)
			messageBytes[getMessageObjectStartIndex() + i] = packetBytes[i];

		return messageBytes;
	}

	// 鍚勪釜鏁版嵁鐨勫紑濮嬩綅
	public static int getSizeStartIndex() {
		return 0;
	}

	public static int getTypeStartIndex() {
		return getSizeStartIndex() + HEAD_INT_SIZE;
	}

	public static int getMessageIdStartIndex() {
		return getTypeStartIndex() + HEAD_INT_SIZE;
	}

	public static int getMessageObjectStartIndex() {
		return getMessageIdStartIndex() + HEAD_FLOAT_SIZE;
	}

	public static void showPacket(Logger logger, IoSession ioSession, byte[] byteArray) {
		try {
			logger.debug("Server send packet to client(" + ServerModel.getIoSessionKey(ioSession) + "); MessageType : "
					+ NetworkPacket.getMessageType(byteArray).toString() + "; MessageId : "
					+ NetworkPacket.getMessageID(byteArray));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
